﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DynamicProperties
{
	/// <summary>
	/// Definition of dynamic property.
	/// </summary>
	public abstract class DynamicProperty
	{
		private const int globalUniqueNumberMax = int.MaxValue;
		private static int globalUniqueNumberCount = 0;

		private static int GetGlobalUniqueNumber()
		{
			// create app domain unique value
			if (globalUniqueNumberCount < globalUniqueNumberMax)
			{
				return ++globalUniqueNumberCount;
			}

			throw new Exception("Too many dynamic properties. Maximum allowed: " + globalUniqueNumberMax.ToString());
		}

		private int globalUniqueNumber;

		public DynamicProperty(string description)
		{
			this.globalUniqueNumber = GetGlobalUniqueNumber();
			this.Description = description;
		}

		public string Description { get; private set; }
		public abstract Type OwnerType { get; }
		public abstract Type PropertyType { get; }

		public override int GetHashCode()
		{
			return this.UniqueInstanceNumber;
		}

		public override bool Equals(object obj)
		{
			DynamicProperty objUnboxed = obj as DynamicProperty;

			if (objUnboxed == null)
				return false;

			if (objUnboxed.UniqueInstanceNumber != UniqueInstanceNumber)
				return false;

			return true;
		}

		/// <summary>
		/// Gets default value for this property.
		/// </summary>
		internal protected abstract object GetDefaultValue();

		/// <summary>
		/// Gets unique number of this instance.
		/// </summary>
		internal int UniqueInstanceNumber
		{
			get
			{
				return this.globalUniqueNumber;
			}
		}

		internal protected abstract void OnPropertyUpdated(object target, object oldValue, object newValue);
	}
}
